/*
 * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

 #include <stdio.h> // 标准输入输出库
 #include <string.h> // 字符串处理库
 #include <unistd.h> // 提供了POSIX操作系统API的头文件
 #include <math.h> // 数学函数库
 #include "ohos_init.h" // OpenHarmony系统初始化相关的头文件
 #include "cmsis_os2.h" // CMSIS RTOS API v2的相关头文件
 #include "iot_gpio.h" // IoT GPIO控制相关的头文件
 #include "hi_io.h" // HiSilicon IO控制相关的头文件
 #include "iot_errno.h" // IoT错误码定义相关的头文件
 #include "hi_adc.h" // ADC（模数转换器）控制相关的头文件
 
 float density, voltage; // 定义浮点型变量density和voltage，用于存储浓度和电压值
 int adcvalue; // 定义整型变量adcvalue，用于存储ADC读取的原始值
 #define COV_RATIO 0.03   // 定义转换比例常量COV_RATIO
 #define NO_DUST_VOLTAGE 230 // 定义无尘环境下的电压阈值NO_DUST_VOLTAGE
 #define SYS_VOLTAGE 7200 // 定义系统电压SYS_VOLTAGE
 
 // 递推平均滤波算法
 double Filter(int m)
 {
     static int flag_first = 0, _buff[10], sum; // 静态变量flag_first、数组_buff和sum，用于滤波计算
     const int _buff_max = 10; // 定义缓冲区最大长度
     int i;
     if (flag_first == 0) // 初始化滤波器
     {
         flag_first = 1; // 设置标志位，表示已初始化
         for (i = 0, sum = 0; i < _buff_max; i++) // 初始化缓冲区并计算初始累加和
         {
             _buff[i] = m;
             sum += _buff[i];
         }
     }
     else // 更新滤波器
     {
         sum -= _buff[0]; // 移除最旧的数据
         for (i = 0; i < (_buff_max - 1); i++) // 将数据左移一位
         {
             _buff[i] = _buff[i + 1];
         }
         _buff[9] = m; // 添加新的数据到缓冲区末尾
         sum += _buff[9]; // 更新累加和
     }
     return  sum/10.0; // 返回滤波后的平均值
 }
 
 // 获取电压值函数
 unsigned int GetVoltage(void)
 {
     unsigned int ret;
     unsigned short data;
     ret = hi_adc_read(HI_ADC_CHANNEL_2, &data, HI_ADC_EQU_MODEL_8, HI_ADC_CUR_BAIS_DEFAULT, 0xff); // ADC读取通道2的数据
     if (ret != IOT_SUCCESS) // 判断是否ADC读取成功
         printf("ADC Read Fail\n"); // 如果失败，打印错误信息
     return data; // 返回读取的ADC数据
 }
 
 // 获取GP2Y传感器数据并计算灰尘浓度
 double GetGP2Y(void)
 {
     IoTGpioSetOutputVal(HI_IO_NAME_GPIO_7, 1); // 设置GPIO_7为输出高电平
     usleep(280); // 延时280微秒
     adcvalue = GetVoltage(); // 读取电压值
     IoTGpioSetOutputVal(HI_IO_NAME_GPIO_7, 0); // 设置GPIO_7为输出低电平
     adcvalue = Filter(adcvalue); // 对ADC值进行滤波处理
     voltage = (SYS_VOLTAGE / 4096.0) * adcvalue * 11; // 计算实际电压值
     if(voltage >= NO_DUST_VOLTAGE) // 判断电压是否超过无尘环境阈值
     {
         voltage -= NO_DUST_VOLTAGE; // 减去无尘环境电压阈值
         density = voltage * COV_RATIO; // 计算灰尘浓度
     }
     else
         density = 0; // 如果电压低于阈值，设置浓度为0
     return density; // 返回计算的灰尘浓度
  }
 
 // ADC任务函数
 static void adc_task(void)
 {
     // 初始化GPIO
     IoTGpioInit(HI_IO_NAME_GPIO_0); // 初始化GPIO_0
     hi_io_set_func(HI_IO_NAME_GPIO_7, HI_IO_FUNC_GPIO_7_GPIO); // 设置GPIO_7的复用功能为普通GPIO
     IoTGpioSetDir(HI_IO_NAME_GPIO_7, IOT_GPIO_DIR_OUT);    // 设置GPIO_7为输出模式
     IoTGpioSetOutputVal(HI_IO_NAME_GPIO_7, 0); // 设置GPIO_7为输出低电平
     while(1) // 无限循环
     {    
         printf("The current dust concentration is:%4.2fug/m3\n ",GetGP2Y()); // 打印当前灰尘浓度
         sleep(1); // 延时1秒
     }
 }
 
 // 创建ADC任务线程
 static void adc_pm2_5(void)
 {
     osThreadAttr_t attr; // 定义线程属性结构体
     attr.attr_bits = 0U; // 初始化线程属性
     attr.cb_mem = NULL; // 回调内存指针设为空
     attr.cb_size = 0U; // 回调内存大小设为0
     attr.stack_mem = NULL; // 线程堆栈内存指针设为空
     attr.stack_size = 1024 * 4; // 设置线程堆栈大小为4KB
 
     attr.name = "adc_task"; // 设置线程名称为"adc_task"
     attr.priority = 25; // 设置线程优先级为25
     if(osThreadNew((osThreadFunc_t)adc_task, NULL, &attr) == NULL) // 创建线程
     {
         printf("Falied to create adc_task!\n"); // 如果创建失败，打印错误信息
     }
 }
 
 APP_FEATURE_INIT(adc_pm2_5); // 注册启动函数adc_pm2_5，在系统初始化时执行